#include <stdio.h>
#include <unistd.h>
#include <pthread.h>

#define PRODUCERS_NUM 2
#define WORKERS_NUM 2
#define QUEUE_LEN 100

/* 请求队列 */
typedef struct request_queue_t {
    int head;
    int tail;
    int size;
    int queue[QUEUE_LEN];
} request_queue_t;


void request_queue_init(request_queue_t *);
int  request_queue_push(request_queue_t *, int);
int  request_queue_pop(request_queue_t *, int *);


static request_queue_t request_queue;
static pthread_mutex_t thread_mutex;
static pthread_cond_t thread_cond;


void request_queue_init (request_queue_t *q) {
    q->head = 0;
    q->tail = 0;
    q->size = 0;
}

int request_queue_push (request_queue_t *q, int item) {
    if (q->size >= QUEUE_LEN) {
        return -1;
    }

    if (q->tail == QUEUE_LEN) {
        q->queue[0] = item;
    } else {
        q->queue[q->tail] = item;
    }

    (q->tail < QUEUE_LEN) ? q->tail++ : (q->tail=0);
    q->size++;

    printf("request queue pushed: %d, size[%d], tail[%d]\n", item, q->size, q->tail);

    return q->size;
}

int request_queue_pop (request_queue_t *q, int *item) {
    if (q->size == 0) {
        return -1;
    }

    if (q->head == QUEUE_LEN) {
        *item = q->queue[0];
    } else {
        *item = q->queue[q->head];
    }

    (q->head < QUEUE_LEN) ? q->head++ : (q->head=0);
    q->size--;

    printf("request queue poped: %d, size[%d], head[%d]\n", *item, q->size, q->head);

    return q->size;
}

void *
producer_process(char *name) {
    request_queue_t *q = &request_queue;

    while (1) {
        // 开锁
        pthread_mutex_lock(&thread_mutex);

        int size = q->size;
        int ret = request_queue_push(&request_queue, size);

        // 解锁
        pthread_mutex_unlock(&thread_mutex);

        // 如果队列满休眠100毫秒
        if (ret == -1) {
            usleep(100);
        }
    }
}

void *
worker_process() {
    int item;

    while (1) {
        // 开锁
        pthread_mutex_lock(&thread_mutex);

        int ret = request_queue_pop(&request_queue, &item);

        // 解锁
        pthread_mutex_unlock(&thread_mutex);

        // 如果队列空休眠100毫秒
        if (ret == -1) {
            usleep(100);
        }
    }
}

void
main (int argc, const char *argv[]) {
    char thread_name[128];

    int threads_total = PRODUCERS_NUM + WORKERS_NUM;

    pthread_t threads_pool[threads_total];

    // thread_info_t threads_info[threads_total];

    // 初始化请求队列
    request_queue_init(&request_queue);

    // 初始化互斥锁
    pthread_mutex_init(&thread_mutex, NULL);

    // 初始化条件变量
    pthread_cond_init(&thread_cond, NULL);

    //创建生产者线程
    for (int i=0; i<PRODUCERS_NUM; i++) {
        sprintf(thread_name, "producer threads[%02d]", i);

        if (pthread_create(&threads_pool[i], NULL, (void *) producer_process, (void *) thread_name) == 0) {
            printf("producer thread created!");
        }
    }

    for (int j=0; j<WORKERS_NUM; j++) {
        sprintf(thread_name, "worker threads[%02d]", j);

        if (pthread_create(&threads_pool[j], NULL, (void *) worker_process, (void *) thread_name) == 0) {
            printf("worker thread created!");
        }
    }

    for (int k=0; k<threads_total; k++) {
        pthread_join(threads_pool[k], NULL);
    }

    // 销毁互斥锁
    pthread_mutex_destroy(&thread_mutex);

    // 销毁条件变量
    pthread_cond_destroy(&thread_cond);
}
